package it.maganar.lesscaos.session;

import it.maganar.lesscaos.entity.Disponibilita;
import it.maganar.lesscaos.entity.Negoziazione;
import it.maganar.lesscaos.entity.Partecipazione;
import it.maganar.lesscaos.entity.User;

import java.util.ArrayList;
import java.util.List;

import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@SuppressWarnings("unchecked")
@Stateless
public class DisponibilitaManagerBean implements DisponibilitaManagerLocal{

	@PersistenceContext(unitName="lessDB")
	protected EntityManager manager;
	
	private PartecipazioniManagerLocal pml;
	
    public DisponibilitaManagerBean() {
    	Context jndiContext;
		try {
			jndiContext = new InitialContext();
			Object ref = jndiContext.lookup("Less-CAOS/PartecipazioniManagerBean/local");
			pml = (PartecipazioniManagerLocal)ref;
		} catch (NamingException e) {
			e.printStackTrace();
		} 
    	
    }

   	@Override
	public void eliminaDisponibilita(int id, String nomeUtente) {
		Disponibilita d;
		d = manager.find(Disponibilita.class, id);
		//d è null se non c'è una disponibilità con l'id richiesto
		if (d != null){
			User u = (User) manager.createQuery("select U from User U where U.nomeUtente =?1").setParameter(1, nomeUtente).getSingleResult();
			//controllo se l'utente ha delle disponibilita
			if (!u.getListaDisponibilita().isEmpty()) {
				u = (User) manager.createQuery("select U from User U join fetch U.listaDisponibilita where U.nomeUtente =?1").setParameter(1, nomeUtente).getSingleResult();
				List<Disponibilita> listaDisponibilita = (List<Disponibilita>)u.getListaDisponibilita();
				for (int i = 0; i < listaDisponibilita.size(); i++) {
					//cerco tra le disponibilita dell'utente quella con l'id indicato
					if (listaDisponibilita.get(i).getId() == id) {
						//se la trovo, la cancello dalla lista delle sue disponibilita
						//in teoria la condizione dell'if è verificata una sola volta
						List listaNuova = new ArrayList();
						listaNuova = u.getListaDisponibilita();
						listaNuova.remove(i);
						u.setListaDisponibilita(listaNuova);
						manager.merge(u);
						manager.flush();
						//cancello anche le partecipazioni associate alla disponibilita appena cancellata
						List listaPartecipazioniAssociate = manager.createQuery("select P from Partecipazione as P join fetch P.iscrizione as D where D.id = ?1").setParameter(1, id).getResultList();
						if (!listaPartecipazioniAssociate.isEmpty()) {
							for (Partecipazione p : (List<Partecipazione>)listaPartecipazioniAssociate) {
								pml.eliminaPartecipazione(p.getId(), p.getRequestor().getNomeUtente());
							}
						}						
					}
				}
				manager.remove(d);
				manager.flush();	
			}
		}
	}

	/**
	 * @return la lista delle disponibilita dell'utente specificato, una lista vuota se l'utente non ha disponibilita
	 */
	@Override
	public List ottieniListaDisponibilita(String nomeUtente) {
		User u = (User) manager.createQuery("select U from User U where U.nomeUtente =?1").setParameter(1, nomeUtente).getSingleResult();
		//controllo se l'utente ha delle disponibilita
		if (u.getListaDisponibilita().isEmpty()) {
			//se non ne ha, ritorno una lista vuota
			return new ArrayList();
		} else {
			//altrimenti carico le sue disponibilita (se le caricassi subito nella prima query JBoss sclera!)
			//e le ritorno
			u = (User) manager.createQuery("select U from User U join fetch U.listaDisponibilita where U.nomeUtente =?1").setParameter(1, nomeUtente).getSingleResult();
			List listaDisponibilita = u.getListaDisponibilita();
			return listaDisponibilita;
		}
	}

	/**
	 * @return la lista delle partecipazioni alle disponibilita dell'utente specificato, 
	 * ossia quelle in cui è in corso una negoziazione o la negozione è terminata in modo positivo
	 */
	@Override
	public List ottieniListaPartecipazioniDisponibilita(String nomeUtente, int id) {
		List listaPartecipazioniOut = new ArrayList();
		List listaPartecipazioni = manager.createQuery("select P from Partecipazione as P join fetch P.iscrizione as D join fetch D.issuer as U where U.nomeUtente = ?1 and D.id = ?2").setParameter(1, nomeUtente).setParameter(2, id).getResultList();
		//controllo se la partecipazione è associata a una negoziazione in corso o a una negoziazione terminata positivamente
		for (int i = 0; i < listaPartecipazioni.size(); i++) {
			//una partecipazione è legata a una sola negoziazione
			Negoziazione negoziazioneAssociata = (Negoziazione) manager.createQuery("select N from Negoziazione as N join fetch N.proposta as P where P.id = ?1").setParameter(1, ((Partecipazione)listaPartecipazioni.get(i)).getId()).getSingleResult();
			if (negoziazioneAssociata.getStato() == 0 || negoziazioneAssociata.getStato() == 1) {
				listaPartecipazioniOut.add(listaPartecipazioni.get(i));
			}
		}
		return listaPartecipazioniOut;
	}

}
